﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using HeritageAcademy.Models.Loaders;
using HeritageAcademy.Models.ViewModels;
using HeritageAcademy.Models;
using HeritageAcademy.Models.DataModels;

namespace HeritageAcademy.Library.Controls
{
    /// <summary>
    /// Логика взаимодействия для TestScroller.xaml
    /// </summary>
    public partial class TestScroller : UserControl
    {
        #region Parameters       
        TestsLoader testsLoader;
        TestsConfigLoader testsConfigLoader;
        UsersConfigLoader user;
        private Test currentTest;
        private bool isLastTest = false;
        #endregion

        #region Ctor
        public TestScroller()
        {
            InitializeComponent();
            testsLoader = new TestsLoader(new Tests());
            testsConfigLoader = new TestsConfigLoader(new TestsData());
            currentTest = new Test();
        }       
        #endregion

        #region Methods
        public void InitializeScroller(Test test)
        {
            user = new UsersConfigLoader(new Users());
            testsLoader = new TestsLoader(new Tests());
            currentTest = test;
                       
            foreach (var page in currentTest.Page)
            {
                List<string> lans = new List<string>();
                foreach (var ans in page.Answers)
                    lans.Add(ans.Value);
                CreateTest(page.Question, lans, Convert2TestType(page.Type), page.Media);
            }

            // Set initial navigation buttons state
            PreviousPageButton.IsEnabled = false;
            NextPageButton.IsEnabled = true;

            // Set initial page numbers
            CurrentPageNumber.Content = 1;
            TotalPageNumber.Content = zsTestScroller.ItemCount;

            // Initialize handlers
            zsTestScroller.CurrentItemChanged += new RoutedPropertyChangedEventHandler<int>(zsTestScroller_CurrentItemChanged);
            NextPageButton.Click += NextPageButton_Click;
            PreviousPageButton.Click += PreviousPageButton_Click;           
        }

        private void Reset()
        {
            zsTestScroller.Items.Clear();

            // Set parameter and first test page
            isLastTest = false;
            zsTestScroller.First();

            zsTestScroller.CurrentItemChanged -= new RoutedPropertyChangedEventHandler<int>(zsTestScroller_CurrentItemChanged);
            NextPageButton.Click -= NextPageButton_Click;
            PreviousPageButton.Click -= PreviousPageButton_Click;
        }

        /// <summary>
        /// Convert test type from letter (ex., "s" or "y") to type (TestType enum).
        /// </summary>
        /// <param name="t">Type as letter (from xml file)</param>
        /// <returns>Type as TestType</returns>
        private TestType Convert2TestType(string t)
        {
            TestType type = TestType.Default;
            switch (t)
            {   
                case "y":
                    type = TestType.YesNo;
                    break;
                case "s":
                    type = TestType.SingleAnswer;
                    break;
                case "m":
                    type = TestType.MultipleAnswers;
                    break;
                default:
                    break;
            }
            return type;
        }

        /// <summary>
        /// Create test.
        /// </summary>
        /// <param name="question">Question string</param>
        /// <param name="answers">Answers string list</param>
        /// <param name="type">Type of test: yes/no, single, multiple</param>
        private void CreateTest(string question, List<string> answers, TestType type, string picturePath)
        {
            CourseTest test = new CourseTest();

            if (!string.IsNullOrEmpty(picturePath))
                test.PicturePath = picturePath;
            test.Question = question.Trim();
            
            switch (type)
            {
                case TestType.YesNo:
                    test.Answers.Children.Add(new RadioButton { 
                                                        HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
                                                        Content = "Да",
                                                        FontSize = 14 // TODO: move to style resource
                                                  }
                                             );
                    test.Answers.Children.Add(new RadioButton {
                                                        HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
                                                        Content = "Нет",
                                                        FontSize = 14 // TODO: move to style resource
                                                  }
                                            );
                    break;
                case TestType.SingleAnswer:                   
                    foreach (var ans in answers)
                    {
                        test.Answers.Children.Add(new RadioButton { 
                                                            HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
                                                            Content = ans,
                                                            FontSize = 14 // TODO: move to style resource
                                                      }
                                                );
                    }
                    break;
                case TestType.MultipleAnswers:
                    foreach (var ans in answers)
                    {
                        test.Answers.Children.Add(new CheckBox { 
                                                        HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
                                                        Content = ans,
                                                        FontSize = 14 // TODO: move to style resource
                                                      }
                                            );
                    }
                    break;
            }
            zsTestScroller.Items.Add(test);
        }

        private void SaveAnswerResult(string studentId, string testId, string pageId, List<string> answerIdList)
        {
            // Gether answers statistics
            string isRight = "true";
            int pageNumber = 0;
            Dictionary<string, string> ansStat = new Dictionary<string, string>();
            foreach (var test in testsLoader.Model.Test)
            {
                if (test.Id == testId)
                {
                    pageNumber = Convert.ToInt32(test.PageNumber); // need it below in code
                    foreach (var page in test.Page)
                    {
                        if (page.Id == pageId)
                        {
                            foreach (var ansId in answerIdList)
                            {
                                foreach (var answer in page.Answers)
                                {
                                    if (answer.id == ansId)
                                    {
                                        if (answer.Status == "true")
                                        {
                                            ansStat.Add(ansId, "true");
                                        }
                                        else
                                        {
                                            ansStat.Add(ansId, "false");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Is answer right or wrong?
            foreach (var stat in ansStat.Values)
            {
                // if ONLY ONE answer in multiple answers question is wrong
                // so the OVERALL answer is WRONG
                if (stat == "false")
                {
                    isRight = "false";
                }
            }

            // Save results
            bool isNewCourse = true;
            bool isNewTest = true;
            bool isNewUser= true;
            foreach (var course in testsConfigLoader.Model.TestCourseData)
            {
                // find appropriate course
                if (course.Id == ((CourseViewModel)DataContext).Model.Identifier)
                {
                    isNewCourse = false;
                    foreach (var test in course.TestData)
                    {
                        // find appropriate test
                        if (test.Id == testId)
                        {
                            isNewTest = false;
                            foreach (var student in test.Student)
                            {
                                // find current user results section
                                if (student.Id == studentId)
                                {
                                    isNewUser = false;
                                    foreach (var page in student.Page)
                                    {
                                        if (page.Id == pageId)
                                        {
                                            page.Status = isRight;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Handle lack of results record
            if (isNewCourse)
            {
                CreateCourseResultsRecord(testsConfigLoader, ((CourseViewModel)DataContext).Model.Identifier);
                SaveAnswerResult(studentId, testId, pageId, answerIdList);
            }
            if (isNewTest)
            {
                CreateTestResultsRecord(testsConfigLoader, ((CourseViewModel)DataContext).Model.Identifier, testId);
                SaveAnswerResult(studentId, testId, pageId, answerIdList);
            }
            if (isNewUser)
            {
                CreateUserResultsRecord(testsConfigLoader, ((CourseViewModel)DataContext).Model.Identifier, testId, studentId, pageNumber);
                SaveAnswerResult(studentId, testId, pageId, answerIdList);
            }
            testsConfigLoader.Save();
        }

        private void CreateCourseResultsRecord(TestsConfigLoader results, string courseId)
        {
            TestCourseData courseResults = new TestCourseData();
            courseResults.Id = courseId;
            results.Model.TestCourseData.Add(courseResults);
            results.Save();
        }

        private void CreateTestResultsRecord(TestsConfigLoader results, string courseId, string testId)
        {
            TestData testResults = new TestData();
            testResults.Id = testId;
            foreach (var course in results.Model.TestCourseData)
            {
                if (course.Id == courseId)
                {
                    course.TestData.Add(testResults);
                }
            }
            results.Save();
        }

        private void CreateUserResultsRecord(TestsConfigLoader results, string courseId, string testId, string studentId, int pageNumber)
        {
            TestStudent studentResults = new TestStudent();
            // add test pages to record
            for (int i = 1; i <= pageNumber; i++)
            {
                TestPage page = new TestPage();
                page.Id = i.ToString();
                page.Status = "false";
                studentResults.Page.Add(page);
            }
            studentResults.Id = studentId;

            // find appropriate place for record
            foreach (var course in results.Model.TestCourseData)
            {
                if (course.Id == courseId)
                {
                    foreach (var test in course.TestData)
                    {
                        if (test.Id == testId)
                        {
                            test.Student.Add(studentResults);
                        }
                    }
                }
            }
            //results.Save();
        }

        #endregion

        #region Event Handlers
        void PreviousPageButton_Click(object sender, RoutedEventArgs e)
        {
            zsTestScroller.Previous();
            if (zsTestScroller.CurrentItemIndex == 0)
                PreviousPageButton.IsEnabled = false;
            if (!NextPageButton.IsEnabled)
                NextPageButton.IsEnabled = true;
            if (isLastTest) isLastTest = false;
        }

        void NextPageButton_Click(object sender, RoutedEventArgs e)
        {           
            if (isLastTest)
            {
                SaveAnswerResult(user.ActiveUser.Id,
                    currentTest.Id,
                    (zsTestScroller.CurrentItemIndex + 1).ToString(),
                    ((CourseTest)zsTestScroller.Items[zsTestScroller.CurrentItemIndex]).GetAnswerIdList());
		        Navigator.Current.ShowTestBoard((CourseViewModel)DataContext);
                Reset();
            }
            else
	        {
                SaveAnswerResult(user.ActiveUser.Id,
                    currentTest.Id,
                    (zsTestScroller.CurrentItemIndex + 1).ToString(),
                    ((CourseTest)zsTestScroller.Items[zsTestScroller.CurrentItemIndex]).GetAnswerIdList());
                zsTestScroller.Next();
                if (zsTestScroller.CurrentItemIndex == zsTestScroller.ItemCount - 1)
                    isLastTest = true;               
                if (!PreviousPageButton.IsEnabled)
                    PreviousPageButton.IsEnabled = true;              
	        }
        }

        void zsTestScroller_CurrentItemChanged(object sender, RoutedPropertyChangedEventArgs<int> e)
        {
            CurrentPageNumber.Content = zsTestScroller.CurrentItemIndex + 1;
        }
        #endregion
    }
}
